package com.rengwuxian.coursecoroutines._1_basics

import android.os.Bundle
import android.os.Handler
import android.os.HandlerThread
import android.os.Looper
import android.widget.TextView
import androidx.activity.ComponentActivity
import androidx.lifecycle.lifecycleScope
import com.rengwuxian.coursecoroutines.R
import com.rengwuxian.coursecoroutines.common.Contributor
import com.rengwuxian.coursecoroutines.common.gitHub
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit
import kotlin.concurrent.thread

/**
 * 「轻量级线程」的本质：从delay()说起
 * 挂起vs阻塞、delay() vs sleep()、轻量级线程
 *
 * kotlin官网说协程是轻量级线程。明确说：协程比线程更省资源
 * 例子中runBlocking会提供一个单线程的ContinuationInterceptor，但是它只能管住里面的协程代码，线程代码不受它管。
 * fun main() = runBlocking<Unit> {
 *   repeat(50_000) {
 *     launch {
 *       delay(500L)
 *       print(".")
 *     }
 *   }
 * }
 * 这50_000个协程，都会运行在同一个线程里面。
 * 如果把launch修改为thread，则就是结结实实开启50_000个线程，当然会报资源（memory）溢出啦。
 * 上面仅仅是kotlin的官方文档希望我们这么写代码：https://kotlinlang.org/docs/coroutines-basics.html#coroutines-are-light-weight
 * 事实上，单线程的代码不是这么去实现的，delay本质上是延时任务，而不是耗时任务，对应的线程代码应该是下面这种：
 *   // 等价的线程代码：
 *   val executor = Executors.newSingleThreadExecutor()
 *   repeat(50_000) {
 *     executor.schedule({
 *       print(".")
 *     }, 500, TimeUnit.MILLISECONDS)
 *   }
 *
 * 再说一个真相，如果把协程切到50_000个线程中执行，也得完蛋。
 * val dispatcher = newFixedThreadPoolContext(50_000, "50k")
 * repeat(50_000) {
 *   launch(dispatcher) {
 *     delay(500L)
 *     print(".")
 *   }
 * }
 *
 * 事物本质是一样的，要去魅
 *
 * delay()是一个挂起函数，它的工作机制，是让出当前线程
 * 而sleep是完全阻塞的
 *
 * 协程的写法，用简单的写法来做复杂逻辑，写出的并发代码就是高性能的，也是一种性能优势。
 */

fun main() = runBlocking<Unit> {
  repeat(50_000) {
    launch {
      delay(500L)
      print(".")
    }
  }

  // 等价的线程代码：
/*  val executor = Executors.newSingleThreadExecutor()
  repeat(50_000) {
    executor.schedule({
      print(".")
    }, 500, TimeUnit.MILLISECONDS)
  }*/
}

class LightWeightCoroutineActivity : ComponentActivity() {
  private lateinit var infoTextView: TextView

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.layout_1)
    infoTextView = findViewById(R.id.infoTextView)

    lifecycleScope.launch {
//      switchToBackground {
//        gitHub.contributors("square", "retrofit")
//        switchToMain {
//          showContributors(contributors)
//        }
//      }
    }
  }

  private fun coroutinesStyle() = lifecycleScope.launch {
    val contributors = gitHub.contributors("square", "retrofit")
    showContributors(contributors)
  }

  private fun showContributors(contributors: List<Contributor>) = contributors
    .map { "${it.login} (${it.contributions})" }
    .reduce { acc, s -> "$acc\n$s" }
    .let { infoTextView.text = it }
}